package com.vecspace.dayu.code.ui.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.vecspace.dayu.code.pojo.DataTable;
import com.vecspace.dayu.code.service.DataTableService;
import com.vecspace.dayu.code.ui.model.ColumnVO;
import com.vecspace.exception.HException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.vecspace.dayu.code.consts.ColumnType;
import com.vecspace.dayu.code.consts.FormElementType;
import com.vecspace.dayu.code.consts.GridCellTextType;
import com.vecspace.dayu.code.pojo.DataColumn;
import com.vecspace.dayu.code.pojo.Func;
import com.vecspace.dayu.code.service.DataColumnService;
import com.vecspace.dayu.code.service.FuncService;
import com.vecspace.dayu.code.template.service.TemplatePageLayoutService;
import com.vecspace.dayu.code.ui.model.PageConfigVO;
import com.vecspace.dayu.code.ui.pojo.DataGrid;
import com.vecspace.dayu.code.ui.pojo.DataGridColumn;
import com.vecspace.dayu.code.ui.pojo.DataTree;
import com.vecspace.dayu.code.ui.pojo.Form;
import com.vecspace.dayu.code.ui.pojo.FormField;
import com.vecspace.dicttable.CodeItem;
import com.vecspace.utils.Assert;
import com.vecspace.utils.BaseModelUtil;
import com.vecspace.utils.Convert;

import comvecspace.data.model.sql.TSqlOperator;

@Service("dayu_pageConfigService")
public class PageConfigService {
	/**获取功能的页面配置信息（一致性获取完整的数据）
	 * 
	 * @param tableId
	 * @param terminalType
	 * @return
	 * @throws Exception 
	 * @author wanghua
	 */
	public PageConfigVO getPageConfigVOByTable(Long tableId, String terminalType) throws Exception {
		DataTable table = dataTableService.getDataTable(tableId);
		Assert.throwz(table != null, "tableId不存在:"+tableId);
		Func func = funcService.getFunc(table.getFuncId());
		Assert.throwz(func != null, "funcId不存在");
		
		PageConfigVO pageConfigVO = new PageConfigVO(func, tableId);
		pageConfigVO.setTerminalType(terminalType);
		pageConfigVO.setTable(table);
		List<DataColumn> dataColumns = dataColumnService.getDataColumns(tableId);
		pageConfigVO.setTableColumns(dataColumns);

		DataTree dataTree = dataTreeService.getDataTreeByTableIdAndTerminalType(tableId, terminalType);
		if(dataTree == null){
			dataTree = new DataTree();
			dataTree.setTableId(tableId);
			dataTree.setPlatformType(terminalType);
		}
		pageConfigVO.setDataTree(dataTree);

		//查询已经存在的DataGrid组件
		DataGrid dataGrid = dataGridService.getDataGridByTableIdAndTerminalType(tableId, terminalType);
		List<DataGridColumn> dataGridColumns;
		if(dataGrid != null) {
			dataGridColumns = dataGridColumnService.getDataGridColumns(dataGrid.getId());
		}else{
			dataGrid = new DataGrid();
			dataGrid.setTableId(tableId);
			dataGrid.setPlatformType(terminalType);
			dataGrid.setPagination(true);
			dataGrid.setPageSize(10);
			dataGrid.setLineNumberColumn(true);
			dataGrid.setGridColumnLine(true);
			dataGrid.setOptrCellEditBtn(true);
			dataGrid.setOptrCellDelBtn(true);
			dataGrid.setToolbarAddBtn(true);
			dataGridColumns = new ArrayList<>();
		}
		pageConfigVO.setDataGrid(dataGrid, dataGridColumns);


		Form form = formService.getFormByTableIdAndTerminalType(tableId, terminalType);
		List<FormField> formFields;
		if(form != null) {
			formFields = formFieldService.getFormFields(form.getId());
		}else{
			form = new Form();
			form.setTableId(tableId);
			form.setPlatformType(terminalType);
			form.setColumnCount(1);
			if(pageConfigVO.getTableColumns() != null) {
				long fldCount = pageConfigVO.getTableColumns().stream().filter(c->c.getMaybeFormField()).count();
				if(fldCount>10) {
					form.setColumnCount(2);
				}
			}
			formFields = new ArrayList<>();
		}
		pageConfigVO.setForm(form, formFields);

		pageConfigVO.buildColumnVOList();

		return pageConfigVO;
	}

	public PageConfigVO savePageConfigVO(PageConfigVO pageConfigVO, String loginId) throws Exception {
		Assert.throwz(pageConfigVO != null, "参数pageConfigVO不能为空");
		Assert.throwz(pageConfigVO.getTableId() != null, "tableId不能为空");
		Assert.throwz(StringUtils.isNotBlank(pageConfigVO.getTerminalType()), "terminalType不能为空");

		List<ColumnVO> columnVOList = pageConfigVO.getColumnVOList();

		StringBuilder errmsg = new StringBuilder(256);

		//检查表单项
		checkFormFields(columnVOList, errmsg);

		if(errmsg.length() > 1){
			throw new HException(errmsg.toString());
		}

		Long tableId = pageConfigVO.getTableId();
		String terminalType = pageConfigVO.getTerminalType();

		List<DataColumn> tableColumns = new ArrayList<>();
		List<DataGridColumn> gridColumns = new ArrayList<>();
		List<FormField> formFields = new ArrayList<>();
		if(columnVOList != null){
			for(ColumnVO columnVO : columnVOList){
				tableColumns.add(columnVO.parseDataColumn());
				if(columnVO.getIsGridColumn()) {
					gridColumns.add(columnVO.parseGridColumn());
				}
				if(columnVO.getIsFormField()) {
					formFields.add(columnVO.parseFormField());
				}
			}
		}

		for(DataColumn column : tableColumns){
			dataColumnService.saveViewDataColumn(column, loginId);
		}

		DataTree dataTree = pageConfigVO.getDataTree();
		dataTreeService.saveViewDataTree(dataTree, loginId);

		DataGrid grid = pageConfigVO.getDataGrid();
		grid = dataGridService.saveViewDataGrid(grid, loginId);
		this.saveViewGridColumns(grid.getId(), gridColumns, loginId);

		Form form = pageConfigVO.getForm();
		form = formService.saveViewForm(form, loginId);
		this.saveViewFormFields(form.getId(), formFields, loginId);

		return  this.getPageConfigVOByTable(tableId, terminalType);
	}

	/**检查表单项FormElementType是否配置正确
	 *
	 * @param columnVOList
	 * @param errmsg
	 * @author wanghua
	 * @date 2021/11/5  12:53
	 * @return  void
	 **/
	private void checkFormFields(List<ColumnVO> columnVOList, StringBuilder errmsg) {
		for(ColumnVO columnVO : columnVOList){
			DataColumn column = columnVO.parseDataColumn();
			if(FormElementType.CHECKBOX.equals(columnVO.getFormElementType()) || FormElementType.SWITCH.equals(columnVO.getFormElementType())) {
				if(!"Boolean".equalsIgnoreCase(column.getJavaType())){
					errmsg.append(String.format("字段%s不是Boolean类型，其表单项不能设置为勾选框和Switch开关\n",columnVO.getColumnName()));
				}
			}

			if(FormElementType.SELECT.equals(columnVO.getFormElementType()) || FormElementType.RADIOS.equals(columnVO.getFormElementType())) {
				if(StringUtils.isBlank(columnVO.getCodeType()) && StringUtils.isBlank(columnVO.getRefTableName())){
					errmsg.append(String.format("字段%s不是字典类型或者外键字段，其表单项不能设置为下拉框和单选按钮组\n",columnVO.getColumnName()));
				}
			}

			if(FormElementType.INTEGER_INPUT.equals(columnVO.getFormElementType())){
				if(!column.getIsNumber()) {
					errmsg.append(String.format("字段%s不是数字类型，其表单项不能设置为整数\n",columnVO.getColumnName()));
				}
			}
			if(FormElementType.FLOAT_INPUT.equals(columnVO.getFormElementType())){
				if(column.getIsIntegerNumber()) {
					errmsg.append(String.format("字段%s是整数类型，其表单项不能设置为浮点数\n",columnVO.getColumnName()));
				}else if(!column.getIsNumber()){
					errmsg.append(String.format("字段%s不是数字类型，其表单项不能设置为浮点数\n",columnVO.getColumnName()));
				}
			}

			if(FormElementType.MULTI_LINE_TEXT.equals(columnVO.getFormElementType())){
				if(!"String".equalsIgnoreCase(column.getJavaType())) {
					errmsg.append(String.format("字段%s不是字符类型，其表单项不能设置为多行文本\n",columnVO.getColumnName()));
				}
			}
			if(FormElementType.DATE.equals(columnVO.getFormElementType())){
				if(!column.getIsDate()) {
					errmsg.append(String.format("字段%s不是日期类型，其表单项不能设置为日期类型\n",columnVO.getColumnName()));
				}
			}
			if(FormElementType.DATE_TIME.equals(columnVO.getFormElementType())){
				if(!column.getIsDateTime()) {
					errmsg.append(String.format("字段%s不是日期+时间类型，其表单项不能设置为日期+时间类型\n",columnVO.getColumnName()));
				}
			}
			if(FormElementType.TIME.equals(columnVO.getFormElementType())){
				if(!"String".equalsIgnoreCase(column.getJavaType())) {
					errmsg.append(String.format("字段%s不是字符类型，其表单项不能设置为不带日期的时间\n",columnVO.getColumnName()));
				}
			}
			if(FormElementType.PERCENT_INPUT.equals(columnVO.getFormElementType())){
				if(!"String".equalsIgnoreCase(column.getJavaType()) && !column.getIsNumber()) {
					errmsg.append(String.format("字段%s不是字符类型或数字行，其表单项不能设置为百分比\n",columnVO.getColumnName()));
				}
			}

			if(FormElementType.TREE_SELECT.equals(columnVO.getFormElementType())){
				if(StringUtils.isBlank(columnVO.getCodeType()) && StringUtils.isBlank(columnVO.getRefTableName())){
					errmsg.append(String.format("字段%s不是字典类型或者外键字段，其表单项不能设置为树形下拉框\n",columnVO.getColumnName()));
				}
			}
		}
	}

	/**数据库中的列和前端传入的列进行对比，然后进行delete，insert 和 update
	 * 
	 * @param gridId
	 * @param custGridColumns
	 * @param loginId
	 * @throws Exception 
	 * @author wanghua
	 */
	private void saveViewGridColumns(Long gridId, List<DataGridColumn> custGridColumns, String loginId) throws Exception {
		List<DataGridColumn> pstGridColumns = dataGridColumnService.getDataGridColumns(gridId);
		//获取删除,先删除在增加。如果先增加，可能会存在唯一性索引冲突的可能性。
		List<DataGridColumn> deletedGridColumns = BaseModelUtil.getDeletedItems(pstGridColumns, custGridColumns);
		for(DataGridColumn column : deletedGridColumns) {
			dataGridColumnService.deleteDataGridColumn(column.getId());
		}
		
		//获取新增
		List<DataGridColumn> newGridColumns = BaseModelUtil.getNewItems(pstGridColumns, custGridColumns);
		for(DataGridColumn column : newGridColumns) {
			column.setDatagridId(gridId);
			dataGridColumnService.saveViewDataGridColumn(column, loginId);
		}
		
		//获取相等
		List<DataGridColumn> eqGridColumns = BaseModelUtil.getEqualItems(pstGridColumns, custGridColumns);
		for(DataGridColumn column : eqGridColumns) {
			//if(column.isEdited()) {
				dataGridColumnService.saveViewDataGridColumn(column, loginId);
			//}
		}
	}
	
	/**  数据库中的列和前端传入的字段进行对比，然后进行delete，insert 和 update
	 * @param formId
	 * @param custFormFields
	 * @param loginId
	 * @throws Exception 
	 * @author wanghua
	 */
	private void saveViewFormFields(Long formId, List<FormField> custFormFields, String loginId) throws Exception {
		List<FormField> pstFormFields = formFieldService.getFormFields(formId);
		//获取删除,先删除在增加。如果先增加，可能会存在唯一性索引冲突的可能性。
		List<FormField> deletedFormFields = BaseModelUtil.getDeletedItems(pstFormFields, custFormFields);
		for(FormField field : deletedFormFields) {
			formFieldService.deleteFormField(field.getId());
		}
		
		//获取新增
		List<FormField> newFormFields = BaseModelUtil.getNewItems(pstFormFields, custFormFields);
		for(FormField field : newFormFields) {
			field.setFormId(formId);
			formFieldService.saveViewFormField(field, loginId);
		}
		
		//获取相等
		List<FormField> eqFormFields = BaseModelUtil.getEqualItems(pstFormFields, custFormFields);
		for(FormField field : eqFormFields) {
			//if(field.isEdited()) {
				formFieldService.saveViewFormField(field, loginId);
			//}
		}
	}
	
	/**将数据库表字段转为表格定义字段
	 * 
	 * @param tableColumnIds 
	 * @throws Exception 
	 * @author wanghua
	 */
	public List<DataGridColumn> transTableColumnToGridColumn(List<Long> tableColumnIds) throws Exception {
		if(tableColumnIds == null || tableColumnIds.size() == 0)return Collections.emptyList();
		List<DataGridColumn> gridColumns = new ArrayList<>(tableColumnIds.size());
		List<DataColumn> tableColumns = dataColumnService.getDataColumns(tableColumnIds);
		int ordnum = 10;
		for(DataColumn tableColumn : tableColumns) {
			DataGridColumn gridColumn = transTableColumnToGridColumn(tableColumn);
			if (gridColumn == null) continue;
			gridColumn.setOrdnum(ordnum);
			ordnum += 10;
			gridColumns.add(gridColumn);
		}
		return gridColumns;
	}

	/**将数据库表字段转为表格定义字段
	 *
	 * @param tableColumn
	 * @throws Exception
	 * @author wanghua
	 */
	private DataGridColumn transTableColumnToGridColumn(DataColumn tableColumn) {
		DataGridColumn gridColumn = new DataGridColumn();
		gridColumn.setColumnId(tableColumn.getId());
		gridColumn.setColumnLabel(tableColumn.getColumnCaption());
		String columnName = tableColumn.getColumnName();
		if(StringUtils.isEmpty(columnName)) {
			return null;
		}
		columnName = columnName.trim().toUpperCase();

		int gridColumnWitdh = 100;
		String javaType = tableColumn.getJavaType();
		int dataLen = Convert.toInt(tableColumn.getDataLength(),0);
		if("String".equals(javaType)) {
			if(dataLen >= 30) {
				gridColumnWitdh = 150;
			}
			if(dataLen >= 100) {
				gridColumnWitdh = 300;
			}
		}
		gridColumn.setColumnWidth(gridColumnWitdh);
		//gridColumn.setColumnName(columnName);
		//gridColumn.setEdited(true);
		String cellTextType = GridCellTextType.TEXT;
		if(StringUtils.isNotBlank(tableColumn.getCodeType())) {
			cellTextType = GridCellTextType.TEXT_DROPLIST;
		}
		gridColumn.setCellTextType(cellTextType);

		if(StringUtils.isNotBlank(tableColumn.getCodeType())) {
			gridColumn.setEditMenu(true);
		}

		gridColumn.setVisibleStatus(true);

		if(StringUtils.isNotBlank(tableColumn.getCodeType())) {
			gridColumn.setQueryField(true);
			gridColumn.setQuerySqlOperator(TSqlOperator.opEqual.toString());
			gridColumn.setQueryVisibleStatus(true);
		}
		if(columnName.endsWith("NAME") || columnName.endsWith("NAME_")) {
			gridColumn.setQueryField(true);
			gridColumn.setQuerySqlOperator(TSqlOperator.opLike.toString());
			gridColumn.setQueryVisibleStatus(true);
		}
		if(tableColumn.getOrdnum() != null) {
			gridColumn.setOrdnum(tableColumn.getOrdnum() * 10);
		}
		return gridColumn;
	}


	/**将数据库表字段转为表格定义字段
	 * 
	 * @param tableColumnIds 
	 * @throws Exception 
	 * @author wanghua
	 */
	public List<FormField> transTableColumnToFormField(List<Long> tableColumnIds) throws Exception {
		if(tableColumnIds == null || tableColumnIds.size() == 0)return Collections.emptyList();
		List<FormField> formFields = new ArrayList<>(tableColumnIds.size());
		List<DataColumn> tableColumns = dataColumnService.getDataColumns(tableColumnIds);
		int ordnum = 10;
		for(DataColumn tableColumn : tableColumns) {
			FormField formField = new FormField();
			formField.setColumnId(tableColumn.getId());
			formField.setColumnLabel(tableColumn.getColumnCaption());
			String columnName = tableColumn.getColumnName();
			if(StringUtils.isEmpty(columnName)) {
				continue;			
			}
			columnName = columnName.trim().toUpperCase();
			//formField.setColumnName(columnName);
			//formField.setEdited(true);
			String javaType = tableColumn.getJavaType();
			String formElementType = FormElementType.TEXT_INPUT;
			
			if(StringUtils.isNotBlank(tableColumn.getCodeType())) {
				formElementType = FormElementType.SELECT;
			} else if(ColumnType.REF_COLUMN.equalsIgnoreCase(tableColumn.getColumnType())) {
				formElementType = FormElementType.SELECT;
			}else if("String".equals(javaType)) {
				formElementType = FormElementType.TEXT_INPUT;
			}else if("LocalDate".equals(javaType)) {
				formElementType = FormElementType.DATE;
			}else if("LocalDateTime".equals(javaType)) {
				formElementType = FormElementType.DATE_TIME;
			}else if("QPercent".equals(javaType)) {
				formElementType = FormElementType.PERCENT_INPUT;
			}else if("Boolean".equals(javaType)) {
				formElementType = FormElementType.CHECKBOX;
			}else if("Integer".equals(javaType)) {
				formElementType = FormElementType.INTEGER_INPUT;
			}else if("Long".equals(javaType)) {
				formElementType = FormElementType.INTEGER_INPUT;				
			}else if("Short".equals(javaType)) {
				formElementType = FormElementType.INTEGER_INPUT;
			}
			else if("BigDecimal".equals(javaType)){
				formElementType = FormElementType.FLOAT_INPUT;
			}			
			formField.setFormElementType(formElementType);

			formField.setRowSpan(1);
			formField.setColSpan(1);
			formField.setOrdnum(ordnum);
			ordnum += 10;
			formFields.add(formField);
		}
		return formFields;
	}
	/**获取pagelayoutId下已经定义的代码类型
	 * 
	 * @param pagelayoutId
	 * @return
	 * @throws Exception 
	 * @author wanghua
	 * @reviewer  
	 * @createTime 2021年9月20日 下午5:45:44
	 */
	public List<CodeItem> getCodeTypes(Long pagelayoutId) throws Exception{
		List<CodeItem> codeTypes = templatePageLayoutService.getCodeTypes(pagelayoutId, true);
		return codeTypes;
	}

	@Autowired
	private FuncService funcService;
	
	@Autowired
	private TemplatePageLayoutService templatePageLayoutService;
	@Autowired
	private DataGridService dataGridService;
	@Autowired
	private DataTreeService dataTreeService;
	@Autowired
	private FormService formService;
	@Autowired
	private DataGridColumnService dataGridColumnService;
	@Autowired
	private DataTableService dataTableService;
	@Autowired
	private FormFieldService formFieldService;
	
	@Autowired
	private DataColumnService dataColumnService;
}
